#ifndef _VECTOR_H_
#define _VECTOR_H_

#include <math.h>
#include "types.h"

class vector2
{
public:
	vector2(){x=0.0f;y=0.0f;}

	vector2(float _x,float _y){x=_x;y=_y;}

	 __forceinline vector2 operator+(vector2& _vec)
	{
		return vector2(x+_vec.x,y+_vec.y); 
	}

	 __forceinline vector2& operator+=(vector2& _vec)
	{
		return *this = *this + _vec; 
	}

	/*operator float*() 
	{ 
		return v; 
	}
	operator const float*() const
	{
		return v; 
	}*/
private:
	union
	{
		struct {float x,y;};
		struct {float v[2];};
	};
};

class vector3
{
public:
	vector3(){x=0.0f;y=0.0f;z=0.0f;}

	vector3(float _x,float _y,float _z){x=_x;y=_y;z=_z;}

	 __forceinline vector3 operator+(vector3& _vec)
	{
		return vector3(x+_vec.x,y+_vec.y,z+_vec.z); 
	}

	 __forceinline vector3& operator+=(vector3& _vec)
	{
		return *this = *this + _vec; 
	}

	 __forceinline vector3& operator*=(float _val)
	{
		x*=_val;
		y*=_val;
		z*=_val;
		return *this; 
	}

	 __forceinline vector3 operator-() const
	{ 
		return vector3(-x,-y,-z); 
	}

	 __forceinline vector3 operator-(vector3 &v) const 
	{ 
		return vector3(x - v.x,y - v.y,z - v.z); 
	}

	 __forceinline vector3 operator*(float _f) const 
	{ 
		return vector3(x*_f,y*_f,z*_f); 
	}

	/*operator float*() 
	{ 
		return v; 
	}*/

	//float& operator[](u32 i)
	//{ 
	//	return ((float*)&x)[i]; 
	//}

	 __forceinline const vector3 operator/(float f) const
	{ 
		return vector3(x / f,y / f,z / f); 
	}

	/*operator const float*() const
	{
		return v; 
	}*/

	 __forceinline float normalize()
	{
		float inv,length = sqrt(x*x+y*y+z*z);
		if(length < 1e-6f) 
			return 0.0;
		inv = 1.0f / length;
		x *= inv;
		y *= inv;
		z *= inv;
		return length;
	}

	 __forceinline vector3 normal() const
	{
		vector3 norm;
		float inv,length = sqrt(x * x + y * y + z * z);
		if(length < 1e-6f) 
			return *this;
		inv = 1.0f / length;
		norm.x = x * inv;
		norm.y = y * inv;
		norm.z = z * inv;
		return norm;
	}

	 __forceinline vector3 cross(const vector3 &v) const 
	{
		vector3 ret;
		ret.x = y * v.z - z * v.y;
		ret.y = z * v.x - x * v.z;
		ret.z = x * v.y - y * v.x;
		return ret;
	}

	 __forceinline static vector3 lerp(vector3& _vec1,vector3 _vec2,float _k)
	{
		vector3 ret;

		ret.x = _vec1.x + (_vec2.x - _vec1.x)*_k;
		ret.y = _vec1.y + (_vec2.y - _vec1.y)*_k;
		ret.z = _vec1.z + (_vec2.z - _vec1.z)*_k;

		return ret;
	}

private:
	union
	{
		struct {float x,y,z;};
		struct {float v[3];};
	};
};

class vector4
{
public:
	vector4(){x=0.0f;y=0.0f;z=0.0f;w=0.0f;}
	vector4(float _x,float _y,float _z,float _w){x=_x;y=_y;z=_z;w=_w;}
private:
	union
	{
		struct {float x,y,z,w;};
		struct {float r,g,b,a;};
		struct {float v[4];};
	};
};

#endif